
// import haxe.macro.Context;
// import haxe.macro.Expr.ExprOf;
// import oimo.m.M;

import { Vec3 } from "../../../common/Vec3";
import { M } from "../../../common/M";



export class BoxBoxDetectorMacro {
	/**
	 * Performs SAT check and minimum depth update for an axis.
	 */
	public static satCheck(minDepth: number, minDepthAxis: Vec3,
		proj1: number, proj2: number, projC12: number, axis: Vec3, id: number): [number, number, number] {
		var sum: number = proj1 + proj2;
		var neg: boolean = projC12 < 0;
		var abs: number = neg ? -projC12 : projC12;
		if (abs < sum) {
			var depth: number = sum - abs;
			if (depth < minDepth) { // giving some bias to edge-edge separating axes
				minDepth = depth;
				minDepthAxis.copyFrom(axis);
				return [minDepth, id, neg ? -1 : 1];
			}
			return [0, 0, 0];
		} else {
			//trace("SA found: id=" + $id + " proj1=" + $proj1 + " proj2=" + $proj2 + " projC12=" + $projC12);
			return;
		}
	}

	public static supportingVertexRect(out: Vec3, halfExtX: Vec3, halfExtY: Vec3, axis: Vec3) {
		var signX: boolean = M.vec3_dot(halfExtX, axis) > 0;
		var signY: boolean = M.vec3_dot(halfExtY, axis) > 0;
		if (signX) {
			if (signY) {
				BoxBoxDetectorMacro.mix2(out, halfExtX, halfExtY, 1, 1);
			} else {
				BoxBoxDetectorMacro.mix2(out, halfExtX, halfExtY, 1, -1);
			}
		} else {
			if (signY) {
				BoxBoxDetectorMacro.mix2(out, halfExtX, halfExtY, -1, 1);
			} else {
				BoxBoxDetectorMacro.mix2(out, halfExtX, halfExtY, -1, -1);
			}
		}
	}

	public static getBoxFace(v1: Vec3, v2: Vec3, v3: Vec3, v4: Vec3, basisX: Vec3, basisY: Vec3, basisZ: Vec3, face: number) {
		switch (face) {
			case 0:
				BoxBoxDetectorMacro.mix3(v1, basisX, basisY, basisZ, 1, 1, 1);
				BoxBoxDetectorMacro.mix3(v2, basisX, basisY, basisZ, 1, -1, 1);
				BoxBoxDetectorMacro.mix3(v3, basisX, basisY, basisZ, 1, -1, -1);
				BoxBoxDetectorMacro.mix3(v4, basisX, basisY, basisZ, 1, 1, -1);
				break;
			case 1:
				BoxBoxDetectorMacro.mix3(v1, basisX, basisY, basisZ, -1, 1, 1);
				BoxBoxDetectorMacro.mix3(v2, basisX, basisY, basisZ, -1, 1, -1);
				BoxBoxDetectorMacro.mix3(v3, basisX, basisY, basisZ, -1, -1, -1);
				BoxBoxDetectorMacro.mix3(v4, basisX, basisY, basisZ, -1, -1, 1);
				break;
			case 2:
				BoxBoxDetectorMacro.mix3(v1, basisX, basisY, basisZ, 1, 1, 1);
				BoxBoxDetectorMacro.mix3(v2, basisX, basisY, basisZ, 1, 1, -1);
				BoxBoxDetectorMacro.mix3(v3, basisX, basisY, basisZ, -1, 1, -1);
				BoxBoxDetectorMacro.mix3(v4, basisX, basisY, basisZ, -1, 1, 1);
				break;
			case 3:
				BoxBoxDetectorMacro.mix3(v1, basisX, basisY, basisZ, 1, -1, 1);
				BoxBoxDetectorMacro.mix3(v2, basisX, basisY, basisZ, -1, -1, 1);
				BoxBoxDetectorMacro.mix3(v3, basisX, basisY, basisZ, -1, -1, -1);
				BoxBoxDetectorMacro.mix3(v4, basisX, basisY, basisZ, 1, -1, -1);
				break;
			case 4:
				BoxBoxDetectorMacro.mix3(v1, basisX, basisY, basisZ, 1, 1, 1);
				BoxBoxDetectorMacro.mix3(v2, basisX, basisY, basisZ, -1, 1, 1);
				BoxBoxDetectorMacro.mix3(v3, basisX, basisY, basisZ, -1, -1, 1);
				BoxBoxDetectorMacro.mix3(v4, basisX, basisY, basisZ, 1, -1, 1);
				break;
			case 5:
				BoxBoxDetectorMacro.mix3(v1, basisX, basisY, basisZ, 1, 1, -1);
				BoxBoxDetectorMacro.mix3(v2, basisX, basisY, basisZ, 1, -1, -1);
				BoxBoxDetectorMacro.mix3(v3, basisX, basisY, basisZ, -1, -1, -1);
				BoxBoxDetectorMacro.mix3(v4, basisX, basisY, basisZ, -1, 1, -1);
				break;
			default:
				console.error("invalid face: " + face);
				break;
		}
	}

	public static mix(dst: Vec3, v: Vec3, sign: number) {
		switch (sign) {
			case 1:
				dst.copyFrom(v);
				break;
			case -1:
				v.negateTo(dst);
				break;
			default:
				console.error("invalid sign: " + sign);
				break;
		}
	}

	public static mix2(dst: Vec3, v1: Vec3, v2: Vec3, sign1: number, sign2: number) {
		if (sign1 == 1 && sign2 == 1) {
			v1.addTo(v2, dst);
		} else if (sign1 == 1 && sign2 == -1) {
			v1.subTo(v2, dst);
		} else if (sign1 == -1 && sign2 == 1) {
			v2.subTo(v1, dst);
		} else if (sign1 == -1 && sign2 == -1) {
			v1.subTo(v2, dst);
			dst.negateEq();
		} else {
			console.error("invalid sign: (" + sign1 + " " + sign2 + ")");
		}
	}

	public static mix3(dst: Vec3, v1: Vec3, v2: Vec3, v3: Vec3, sign1: number, sign2: number, sign3: number) {
		switch (sign3) {
			case 1:
				BoxBoxDetectorMacro.mix2(dst, v1, v2, sign1, sign2);
				dst.addEq(v3);
				break;
			case -1:
				BoxBoxDetectorMacro.mix2(dst, v1, v2, sign1, sign2);
				dst.addEq(v3);
				break;
			default:
				console.error("invalid sign: (" + sign1 + " " + sign2 + " " + sign3 + ")");
				break;
		}
	}

	public static swapV(tmp: Vec3, v1: Vec3, v2: Vec3) {
		tmp.copyFrom(v1);
		v1.copyFrom(v2);
		v2.copyFrom(tmp);
	}

}
